/* nd-sha1.c - Functions to compute SHA1 message digest of
   files or memory blocks according to the NIST
   specification FIPS-180-1.

   Copyright (C) 2000-2001, 2003-2006, 2008-2017 Free
   Software Foundation, Inc.

   This program is free software; you can redistribute it
   and/or modify it under the terms of the GNU General
   Public License as published by the Free Software
   Foundation; either version 3, or (at your option) any
   later version.

   This program is distributed in the hope that it will be
   useful, but WITHOUT ANY WARRANTY; without even the
   implied warranty of MERCHANTABILITY or FITNESS FOR A
   PARTICULAR PURPOSE.  See the GNU General Public License
   for more details.

   You should have received a copy of the GNU General Public
   License along with this program; if not, see
   <https://www.gnu.org/licenses/>.  */

/* Written by Scott G. Miller
   Credits:
      Robert Klep <robert@ilse.nl>  -- Expansion function
   fix
*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#ifdef HAVE_STDALIGN_H
#include <stdalign.h>
#endif
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

#include "nd-sha1.h"

#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define SWAP(n) (n)
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define SWAP(n) \
    (((n) << 24) | (((n)&0xff00) << 8) | \
      (((n) >> 8) & 0xff00) | ((n) >> 24))
#else
#error Endianess not defined (__BYTE_ORDER__).
#endif

#define BLOCKSIZE 32768
#if BLOCKSIZE % 64 != 0
#error "invalid BLOCKSIZE"
#endif

/* This array contains the bytes used to pad the buffer to
   the next 64-byte boundary.  (RFC 1321, 3.1: Step 1)  */
static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ...  */ };

/* Take a pointer to a 160 bit block of data (five 32 bit
   ints) and initialize it to the start constants of the
   SHA1 algorithm.  This must be called before using hash in
   the call to sha1_hash.  */
void sha1_init(sha1 *ctx) {
    ctx->A = 0x67452301;
    ctx->B = 0xefcdab89;
    ctx->C = 0x98badcfe;
    ctx->D = 0x10325476;
    ctx->E = 0xc3d2e1f0;

    ctx->total[0] = ctx->total[1] = 0;
    ctx->buflen                   = 0;
}

/* Copy the 4 byte value from v into the memory location
   pointed to by *cp, If your architecture allows unaligned
   access this is equivalent to
   * (uint32_t *) cp = v  */
static void set_uint32(char *cp, uint32_t v) {
    memcpy(cp, &v, sizeof v);
}

/* Put result from CTX in first 20 bytes following RESBUF.
   The result must be in little endian byte order.  */
void *sha1_read(const sha1 *ctx, void *resbuf) {
    char *r = resbuf;
    set_uint32(r + 0 * sizeof ctx->A, SWAP(ctx->A));
    set_uint32(r + 1 * sizeof ctx->B, SWAP(ctx->B));
    set_uint32(r + 2 * sizeof ctx->C, SWAP(ctx->C));
    set_uint32(r + 3 * sizeof ctx->D, SWAP(ctx->D));
    set_uint32(r + 4 * sizeof ctx->E, SWAP(ctx->E));

    return resbuf;
}

/* Process the remaining bytes in the internal buffer and
   the usual prolog according to the standard and write the
   result to RESBUF.  */
void *sha1_result(sha1 *ctx, void *resbuf) {
    /* Take yet unprocessed bytes into account.  */
    uint32_t bytes = ctx->buflen;
    size_t size    = (bytes < 56) ? 64 / 4 : 64 * 2 / 4;

    /* Now count remaining bytes.  */
    ctx->total[0] += bytes;
    if (ctx->total[0] < bytes) ++ctx->total[1];

    /* Put the 64-bit file length in *bits* at the end of the
   * buffer.  */
    ctx->buffer[size - 2] = SWAP((ctx->total[1] << 3) |
      (ctx->total[0] >> 29));
    ctx->buffer[size - 1] = SWAP(ctx->total[0] << 3);

    memcpy(&((char *)ctx->buffer)[bytes], fillbuf,
      (size - 2) * 4 - bytes);

    /* Process last bytes.  */
    sha1_write_block(ctx, ctx->buffer, size * 4);

    return sha1_read(ctx, resbuf);
}

void sha1_write(sha1 *ctx, const void *buffer, size_t len) {
    /* When we already have some bits in our internal buffer
     concatenate both inputs first.  */
    if (ctx->buflen != 0) {
        size_t left_over = ctx->buflen;
        size_t add = 128 - left_over > len ? len : 128 - left_over;

        memcpy(&((char *)ctx->buffer)[left_over], buffer, add);
        ctx->buflen += add;

        if (ctx->buflen > 64) {
            sha1_write_block(ctx, ctx->buffer, ctx->buflen & ~63);

            ctx->buflen &= 63;
            /* The regions in the following copy operation cannot
         overlap, because ctx->buflen < 64 ≤ (left_over +
         add) & ~63.  */
            memcpy(ctx->buffer,
              &((char *)ctx->buffer)[(left_over + add) & ~63],
              ctx->buflen);
        }

        buffer = (const char *)buffer + add;
        len -= add;
    }

    /* Process available complete blocks.  */
    if (len >= 64) {
#if ! (_STRING_ARCH_unaligned || _STRING_INLINE_unaligned)
#define UNALIGNED_P(p) \
    ((uintptr_t)(p) % alignof(uint32_t) != 0)
        if (UNALIGNED_P(buffer))
            while (len > 64) {
                sha1_write_block(ctx,
                  memcpy(ctx->buffer, buffer, 64), 64);
                buffer = (const char *)buffer + 64;
                len -= 64;
            }
        else
#endif
        {
            sha1_write_block(ctx, buffer, len & ~63);
            buffer = (const char *)buffer + (len & ~63);
            len &= 63;
        }
    }

    /* Move remaining bytes in internal buffer.  */
    if (len > 0) {
        size_t left_over = ctx->buflen;

        memcpy(&((char *)ctx->buffer)[left_over], buffer, len);
        left_over += len;
        if (left_over >= 64) {
            sha1_write_block(ctx, ctx->buffer, 64);
            left_over -= 64;
            /* The regions in the following copy operation cannot
         overlap, because left_over ≤ 64.  */
            memcpy(ctx->buffer, &ctx->buffer[16], left_over);
        }
        ctx->buflen = left_over;
    }
}

/* SHA1 round constants */
#define K1 0x5a827999
#define K2 0x6ed9eba1
#define K3 0x8f1bbcdc
#define K4 0xca62c1d6

/* Round functions.  Note that F2 is the same as F4.  */
#define F1(B, C, D) (D ^ (B & (C ^ D)))
#define F2(B, C, D) (B ^ C ^ D)
#define F3(B, C, D) ((B & C) | (D & (B | C)))
#define F4(B, C, D) (B ^ C ^ D)

/* Process LEN bytes of BUFFER, accumulating context into
   CTX. It is assumed that LEN % 64 == 0. Most of this code
   comes from GnuPG's cipher/sha1.c.  */

void sha1_write_block(sha1 *ctx, const void *buffer, size_t len) {
    const uint32_t *words = buffer;
    size_t nwords         = len / sizeof(uint32_t);
    const uint32_t *endp  = words + nwords;
    uint32_t x[16];
    uint32_t a     = ctx->A;
    uint32_t b     = ctx->B;
    uint32_t c     = ctx->C;
    uint32_t d     = ctx->D;
    uint32_t e     = ctx->E;
    uint32_t lolen = len;

    /* First increment the byte count.  RFC 1321 specifies the
     possible length of the file up to 2^64 bits.  Here we
     only compute the number of bytes.  Do a double word
     increment.  */
    ctx->total[0] += lolen;
    ctx->total[1] += (len >> 31 >> 1) + (ctx->total[0] < lolen);

#define rol(x, n) \
    (((x) << (n)) | ((uint32_t)(x) >> (32 - (n))))

#define M(I) \
    (tm = x[I & 0x0f] ^ x[(I - 14) & 0x0f] ^ \
        x[(I - 8) & 0x0f] ^ x[(I - 3) & 0x0f], \
      (x[I & 0x0f] = rol(tm, 1)))

#define R(A, B, C, D, E, F, K, M) \
    do { \
        E += rol(A, 5) + F(B, C, D) + K + M; \
        B = rol(B, 30); \
    } \
    while (0)

    while (words < endp) {
        uint32_t tm;
        int t;
        for (t = 0; t < 16; t++) {
            x[t] = SWAP(*words);
            words++;
        }

        R(a, b, c, d, e, F1, K1, x[0]);
        R(e, a, b, c, d, F1, K1, x[1]);
        R(d, e, a, b, c, F1, K1, x[2]);
        R(c, d, e, a, b, F1, K1, x[3]);
        R(b, c, d, e, a, F1, K1, x[4]);
        R(a, b, c, d, e, F1, K1, x[5]);
        R(e, a, b, c, d, F1, K1, x[6]);
        R(d, e, a, b, c, F1, K1, x[7]);
        R(c, d, e, a, b, F1, K1, x[8]);
        R(b, c, d, e, a, F1, K1, x[9]);
        R(a, b, c, d, e, F1, K1, x[10]);
        R(e, a, b, c, d, F1, K1, x[11]);
        R(d, e, a, b, c, F1, K1, x[12]);
        R(c, d, e, a, b, F1, K1, x[13]);
        R(b, c, d, e, a, F1, K1, x[14]);
        R(a, b, c, d, e, F1, K1, x[15]);
        R(e, a, b, c, d, F1, K1, M(16));
        R(d, e, a, b, c, F1, K1, M(17));
        R(c, d, e, a, b, F1, K1, M(18));
        R(b, c, d, e, a, F1, K1, M(19));
        R(a, b, c, d, e, F2, K2, M(20));
        R(e, a, b, c, d, F2, K2, M(21));
        R(d, e, a, b, c, F2, K2, M(22));
        R(c, d, e, a, b, F2, K2, M(23));
        R(b, c, d, e, a, F2, K2, M(24));
        R(a, b, c, d, e, F2, K2, M(25));
        R(e, a, b, c, d, F2, K2, M(26));
        R(d, e, a, b, c, F2, K2, M(27));
        R(c, d, e, a, b, F2, K2, M(28));
        R(b, c, d, e, a, F2, K2, M(29));
        R(a, b, c, d, e, F2, K2, M(30));
        R(e, a, b, c, d, F2, K2, M(31));
        R(d, e, a, b, c, F2, K2, M(32));
        R(c, d, e, a, b, F2, K2, M(33));
        R(b, c, d, e, a, F2, K2, M(34));
        R(a, b, c, d, e, F2, K2, M(35));
        R(e, a, b, c, d, F2, K2, M(36));
        R(d, e, a, b, c, F2, K2, M(37));
        R(c, d, e, a, b, F2, K2, M(38));
        R(b, c, d, e, a, F2, K2, M(39));
        R(a, b, c, d, e, F3, K3, M(40));
        R(e, a, b, c, d, F3, K3, M(41));
        R(d, e, a, b, c, F3, K3, M(42));
        R(c, d, e, a, b, F3, K3, M(43));
        R(b, c, d, e, a, F3, K3, M(44));
        R(a, b, c, d, e, F3, K3, M(45));
        R(e, a, b, c, d, F3, K3, M(46));
        R(d, e, a, b, c, F3, K3, M(47));
        R(c, d, e, a, b, F3, K3, M(48));
        R(b, c, d, e, a, F3, K3, M(49));
        R(a, b, c, d, e, F3, K3, M(50));
        R(e, a, b, c, d, F3, K3, M(51));
        R(d, e, a, b, c, F3, K3, M(52));
        R(c, d, e, a, b, F3, K3, M(53));
        R(b, c, d, e, a, F3, K3, M(54));
        R(a, b, c, d, e, F3, K3, M(55));
        R(e, a, b, c, d, F3, K3, M(56));
        R(d, e, a, b, c, F3, K3, M(57));
        R(c, d, e, a, b, F3, K3, M(58));
        R(b, c, d, e, a, F3, K3, M(59));
        R(a, b, c, d, e, F4, K4, M(60));
        R(e, a, b, c, d, F4, K4, M(61));
        R(d, e, a, b, c, F4, K4, M(62));
        R(c, d, e, a, b, F4, K4, M(63));
        R(b, c, d, e, a, F4, K4, M(64));
        R(a, b, c, d, e, F4, K4, M(65));
        R(e, a, b, c, d, F4, K4, M(66));
        R(d, e, a, b, c, F4, K4, M(67));
        R(c, d, e, a, b, F4, K4, M(68));
        R(b, c, d, e, a, F4, K4, M(69));
        R(a, b, c, d, e, F4, K4, M(70));
        R(e, a, b, c, d, F4, K4, M(71));
        R(d, e, a, b, c, F4, K4, M(72));
        R(c, d, e, a, b, F4, K4, M(73));
        R(b, c, d, e, a, F4, K4, M(74));
        R(a, b, c, d, e, F4, K4, M(75));
        R(e, a, b, c, d, F4, K4, M(76));
        R(d, e, a, b, c, F4, K4, M(77));
        R(c, d, e, a, b, F4, K4, M(78));
        R(b, c, d, e, a, F4, K4, M(79));

        a = ctx->A += a;
        b = ctx->B += b;
        c = ctx->C += c;
        d = ctx->D += d;
        e = ctx->E += e;
    }
}
